package com.homson.coreservice.serviceinfrastructure.datasource.repository.account;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.homson.coreservice.servicecommon.co.AccountCreateCO;
import com.homson.coreservice.servicecommon.enumeration.AccountTypeEnum;
import com.homson.coreservice.servicecommon.enumeration.CurrencyEnum;
import com.homson.coreservice.servicecommon.enumeration.ValidStatus;
import com.homson.coreservice.serviceinfrastructure.datasource.mapper.AccountMapper;
import com.homson.coreservice.serviceinfrastructure.datasource.model.account.AccountDO;
import com.homson.coreservice.serviceinfrastructure.datasource.repository.BaseRepository;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Repository;

import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;

/**
 * @author: homson_leo
 * @contact: hey_超级巨星（Homson_Leo）- 刘泓岑 1196816884@qq.com
 * @time: 2025/10/4 10:59 AM
 **/
@Repository
@Slf4j
public class AccountRepository extends BaseRepository<AccountMapper, AccountDO> {
    
    @Resource
    private AccountMapper accountMapper;
    
    public List<AccountDO> findAllAccountByPage(Long userId, Integer pageNum, Integer pageSize){
        if (Objects.isNull(pageNum) || pageNum < 1) {
            pageNum = 1;
        }
        if (Objects.isNull(pageSize) || pageSize <= 0) {
            pageSize = 10;
        }
        IPage<AccountDO> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<AccountDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(AccountDO::getUserId, userId)
                .eq(AccountDO::getStatus, ValidStatus.VALID.name());
        
        IPage<AccountDO> accountDOs = accountMapper.selectPage(page, wrapper);
        return accountDOs.getRecords();
    }
    
    public Boolean isAccountExist(AccountTypeEnum accountType, String accountName) {
        LambdaQueryWrapper<AccountDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(AccountDO::getType, accountType.name())
                .eq(AccountDO::getName, accountName)
                .eq(AccountDO::getStatus, ValidStatus.VALID.name());
        return this.exists(wrapper);
    }
    
    public void createAccount(Long accountId, AccountCreateCO accountCO) {
        AccountDO accountDo = new AccountDO();
        accountDo.setAccountId(accountId);
        accountDo.setUserId(accountCO.getUserId());
        accountDo.setName(accountCO.getAccountName());
        accountDo.setType(AccountTypeEnum.of(accountCO.getAccountType()).name());
        accountDo.setCurrency(CurrencyEnum.of(accountCO.getCurrency()).getCurrencyEnName());
        accountDo.setBalance(accountCO.getBalance());
        accountDo.setStatus(ValidStatus.VALID.name());
        accountDo.createTime();
        accountDo.updateTime();
        accountDo.lastUpdated();
        accountDo.incrementVersionId();
        this.saveOrUpdate(accountDo);
    }
    
    
    public AccountDO findByAccountId(Long accountId) {
        LambdaQueryWrapper<AccountDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(AccountDO::getAccountId, accountId)
                .eq(AccountDO::getStatus, ValidStatus.VALID.name());
        return getOne(wrapper);
    }
    
    public List<AccountDO> findByAccountIds(List<Long> accountIds) {
        LambdaQueryWrapper<AccountDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(AccountDO::getAccountId, accountIds)
                .eq(AccountDO::getStatus, ValidStatus.VALID.name());
        return list(wrapper);
    }
    
    public AccountDO findByAccountIdAndType(Long accountId, String type) {
        LambdaQueryWrapper<AccountDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(AccountDO::getAccountId, accountId)
                .eq(AccountDO::getType, type)
                .eq(AccountDO::getStatus, ValidStatus.VALID.name());
        return getOne(wrapper);
    }
    
    public List<AccountDO> findAllByUserId(Long userId){
        LambdaQueryWrapper<AccountDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(AccountDO::getUserId, userId)
                .eq(AccountDO::getStatus, ValidStatus.VALID.name());
        return list(wrapper);
    }
    
    public void updateAccountBalance(Long accountId, BigDecimal balance, Long versionId){
        AccountDO accountDO = findByAccountId(accountId);
        if(Objects.isNull(accountDO)){
            log.error(AccountRepository.class.getSimpleName(),String.format("更新失败账户ID:%s不存在", accountId));
            return;
        }
        if(!accountDO.getVersionId().equals(versionId)){
            log.error(AccountRepository.class.getSimpleName(),String.format("更新账户:%s失败，CAS冲突", accountId));
            throw new RuntimeException("CAS冲突");
        }
        accountDO.setBalance(balance);
        accountDO.updateTime();
        accountDO.lastUpdated();
        accountDO.incrementVersionId();
        this.updateById(accountDO);
    }
   

}
